﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EasyTrader.Manager
{
    public class JisuWaveSysManager : SysManager
    {
        // 이 함수는 현재 상태가 상승인지 하락인지 판단을 한다. 새로운 상태가 나오면 새로운 상태를 등록한다.
        // 신호 파동의 끝점에서 전체 신호 파동의 15%를 반등 혹은 반락 했을 때 상태를 전환시킨다.
        // 이때 신호 파동의 높이와 상관없이 15%를 했을 때 0.35를 넘으면 전환을 시킨다. 
        // 돌파는 고점에서 3틱(0.15)를 넘으면 전환시킨다.
        private void FindCurState()
        {
            //return m_TotalSigMan.FindState(m_SysType, m_FirstSig, m_PriceStateList, m_LogFileName, ref m_CurState);

            // 시스템 상태를 확인한다.
            EasyTrader.Signal.PriceSignal curState = FindSysState();
            // 시스템 상태가 바뀌었을 경우 확인하고 신호정보를 복사하여 추가한다.
            m_TotalSigMan.CheckAddState(m_TotalSigMan.CurIndex, m_PriceStateList, curState);
        }

        private EasyTrader.Signal.PriceSignal FindSysState()
        {
            //return m_TotalSigMan.FindState(m_SysType, m_FirstSig, m_PriceStateList, m_LogFileName, ref m_CurState);
            if (m_PriceStateList.Count == 0)
            {
                return m_TotalSigMan.FindFirstSignalBySysType(GlobalVar.SysTypeJisuWave, JisuWaveSysVar.FirstSignalType, m_LogFileName, ref m_CurState);
            }

            if (m_TotalSigMan.ETHighLowSignalManager == null || m_TotalSigMan.ETWaveSignalManager == null)
                return null;
            double curVal = m_TotalSigMan.CurVal;
            if (curVal == 0.0)
                return null;
            // 이전에 발생한 신호를 가져온다.
            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);
            // 신호를 발생시킬 고저 폭을 구한다.
            //HighLowInfo m_HighLowInfo = m_ETWaveSignalManager.FindSignalHeightInfo(a_CurIndex);
            // 현재 파동을 가져온다.
            EasyTrader.Wave.PriceWave curWave = m_TotalSigMan.ETWaveSignalManager.EasyTraderWaveManager.GetCurWave(m_TotalSigMan.CurIndex);
            if (m_TotalSigMan.SignalHighLowInfo == null || curWave == null || lastState == null)
                return null;

            double dayAmp = m_TotalSigMan.GetDayAmp();

            // 최소 높이에서는 반응하지 않는다.
            if (dayAmp <= JisuWaveSysVar.MinTurnHeight)
                return null;

            if (lastState.Type == GlobalVar.SignalBuy)
            {
                double lastLowY = lastState.SignalMin;
                double limitLowVal = lastLowY - 0.15;
                if (curWave.Slope == GlobalVar.PriceDown && curVal < limitLowVal)
                {
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateOver, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매도로상태전환(돌파)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }
            else if (lastState.Type == GlobalVar.SignalSell)
            {
                double lasthighY = lastState.SignalMax;
                double limitHighVal = lasthighY + 0.15;
                if (curWave.Slope == GlobalVar.PriceUp && curVal > limitHighVal)
                {
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateOver, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매수로상태전환(돌파)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }

            double SigHigh = m_TotalSigMan.SignalHighLowInfo.HighY;
            double SigLow = m_TotalSigMan.SignalHighLowInfo.LowY;
            double SigHeight = Math.Abs(SigHigh - SigLow);
            double limitHeight = SigHeight * 0.15;
            double lowLimit = SigLow + limitHeight;
            double highLimit = SigHigh - limitHeight;

            double lowRootLimit = m_TotalSigMan.SignalHighLowInfo.LowY + GlobalVar.WaveRootLimit;
            double highRootlLimit = m_TotalSigMan.SignalHighLowInfo.HighY - GlobalVar.WaveRootLimit;

            // 15% 이상에서 최고 전환 높이보다 작을 때는 신호를 발생하지 않는다.
            if (SigHeight < JisuWaveSysVar.MinDayAmp && limitHeight < JisuWaveSysVar.MinTurnHeight)
                return null;

            if (curWave.LowY <= lowRootLimit && curWave.Slope == GlobalVar.PriceUp && curVal >= lowLimit)
            {
                if (lastState.Type == GlobalVar.SignalSell)
                {
                    // 매수로 전환
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매수로상태전환(일반)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }
            if (curWave.HighY >= highRootlLimit && curWave.Slope == GlobalVar.PriceDown && curVal <= highLimit)
            {
                if (lastState.Type == GlobalVar.SignalBuy)
                {
                    // 매도로 전환
                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                    m_TotalSigMan.WriteStateLog("매도로상태전환(일반)", m_LogFileName, m_CurState);
                    return m_CurState;
                }
            }

            return null;
        }

        // 상태를 바탕으로 신호를 발생시킨다.
        private void CheckSignal()
        {
            if (JisuWaveSysVar.LastSignalFired == true)
                return;

            // 먼저 상태 개수를 확인한다.
            // 정해진 상태 개수 안에서만 신호를 발생시킨다.
            int stateCount = m_PriceStateList.Count;
            if (stateCount < JisuWaveSysVar.SysStartState ||
                stateCount > JisuWaveSysVar.SysEndState)
                return;

            // 먼저 청산을 확인한다.
            // 가격에 의한 청산 신호가 있는지 확인한다.
            EasyTrader.Signal.PriceSignal curSignal = GetLiquidSignalByTotalPrice();
            EasyTrader.Signal.PriceSignal activeSignal = null;
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                JisuWaveSysVar.AutoOrder = false;
                JisuWaveSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(JisuWaveSysVar.AutoOrder, GlobalVar.SysTypeJisuWave);
            }

            curSignal = GetLiquidSignalByMaxPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                JisuWaveSysVar.AutoOrder = false;
                JisuWaveSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(JisuWaveSysVar.AutoOrder, GlobalVar.SysTypeJisuWaveHogaSummit);
            }

            curSignal = GetLiquidSignalByTotalPriceStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                // 단계별 총 청산액을 증가시켜 준다.
                JisuWaveSysVar.TotalProfitStepLiquidVal += JisuWaveSysVar.StepLiquidVal;
            }

            curSignal = GetLiquidSignalByStateCountStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                // 단계별 상태값을 증가시켜 준다.
                JisuWaveSysVar.StepLiquidStateCount++;
            }

            curSignal = GetLiquidSignalByPerPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
            }
            // 시간에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByTime();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                JisuWaveSysVar.AutoOrder = false;
                JisuWaveSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(JisuWaveSysVar.AutoOrder, GlobalVar.SysTypeJisuWave);
            }
            // 상태 개수에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByStateCount();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
                JisuWaveSysVar.AutoOrder = false;
                JisuWaveSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(JisuWaveSysVar.AutoOrder, GlobalVar.SysTypeJisuWave);
            }
            // 상태 전환에 의한 신호가 있는지 확인한다.
            curSignal = GetSignalByStateChange();
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                SendOrder(activeSignal);
            }
        }
        
        public void UpdateSysState()
        {
            Console.WriteLine("JisuWave Sys Index = " + m_TotalSigMan.CurIndex.ToString());
            FindCurState();
            CheckSignal();
        }
    }
}
